package deployr.http;

import static deployr.core.Files.*;
import static deployr.core.Streams.*;
import static java.text.MessageFormat.*;
import static org.junit.Assert.*;

import java.net.*;

import org.junit.*;

import deployr.cli.*;
import deployr.client.api.*;
import deployr.core.*;
import deployr.domain.*;

public class DeployrUpdateIT {

	private static JettyServer server;
	private static UpdateProcess updateProcess;
	private Workspace workspace;
	private static DeployrApi deployr;

	@BeforeClass
	public static void setUpClass() {
		server = new JettyServer();
		server.run("localhost", 9090, file(target("jetty")), file(target("jetty/workspaces/user/webapps")));

		deployr = new Deployr("http://localhost:9090");
		updateProcess = new UpdateProcess(deployr, "hello-1.0", "");
	}

	@Before
	public void setUp() {
		workspace = new Workspace("user", new FileSystem(file(target("jetty"))));
		deployr.deleteUpdates("hello-1.0");
		deployr.createProject("hello-1.0");
	}

	@AfterClass
	public static void tearDownClass() {
		server.stop();
	}
	
	@Test
	public void shouldUpdateHello1() {
		updateProcess.update(new Path(testResources("webapps/hello1")));

		sleep(2);

		assertTrue(workspace.exist("/projects/hello/hello/1.0/checksum"));
		assertTrue(workspace.exist("/projects/hello/hello/1.0/metadata"));

		assertTrue(workspace.exist("/projects/hello/1.0/updates/1/checksum"));
		assertTrue(workspace.exist("/projects/hello/1.0/updates/1/diff"));
		assertTrue(workspace.exist("/projects/hello/1.0/updates/1/metadata"));

		assertTrue(workspace.exist("/assets/747bd6385871f3db959d94db723d73a6078d6772"));
		assertTrue(workspace.exist("/assets/ba70d47b2df53f8c7a2e318dbd6e2b040ceef94f"));

		assertEquals("hello1", GET("http://localhost:9090/hello-1.0/hello"));
		assertEquals("hello1", GET("http://localhost:9090/hello-1.0u1/hello"));
	}

	@Test
	public void shouldUpdateHello2() {
		updateProcess.update(new Path(testResources("webapps/hello1")));
		updateProcess.update(new Path(testResources("webapps/hello2")));

		sleep(2);

		assertTrue(workspace.exist("/projects/hello/hello/1.0/checksum"));
		assertTrue(workspace.exist("/projects/hello/hello/1.0/metadata"));

		assertTrue(workspace.exist("/projects/hello/1.0/updates/2/checksum"));
		assertTrue(workspace.exist("/projects/hello/1.0/updates/2/diff"));
		assertTrue(workspace.exist("/projects/hello/1.0/updates/2/metadata"));

		assertTrue(workspace.exist("/assets/36ab51f92125e611df539cebacc1bca9159bc40a"));
		assertTrue(workspace.exist("/assets/2699b42bf064dcdf7cd1a4580a2fb9da7384b4bd"));

		assertEquals("hello2", GET("http://localhost:9090/hello-1.0/hello"));
		assertEquals("hello2", GET("http://localhost:9090/hello-1.0u2/hello"));
	}

	@Test
	public void shouldUpdateSomeTimesSameApp() {
		updateProcess.update(new Path(testResources("webapps/hello1")));
		updateProcess.update(new Path(testResources("webapps/hello1")));
		updateProcess.update(new Path(testResources("webapps/hello1")));
		updateProcess.update(new Path(testResources("webapps/hello1")));
		updateProcess.update(new Path(testResources("webapps/hello1")));
		updateProcess.update(new Path(testResources("webapps/hello1")));
	}
	
	@Test
	public void shouldUpdateHello3() {
		updateProcess.update(new Path(testResources("webapps/hello1")));
		updateProcess.update(new Path(testResources("webapps/hello2")));
		updateProcess.update(new Path(testResources("webapps/hello3")));

		sleep(2);

		assertTrue(workspace.exist("/projects/hello/hello/1.0/checksum"));
		assertTrue(workspace.exist("/projects/hello/hello/1.0/metadata"));

		assertTrue(workspace.exist("/projects/hello/1.0/updates/3/checksum"));
		assertTrue(workspace.exist("/projects/hello/1.0/updates/3/diff"));
		assertTrue(workspace.exist("/projects/hello/1.0/updates/3/metadata"));

		assertTrue(workspace.exist("/assets/6f8abebbd233fcaf0259f776b5b4f0e70f346c4e"));
		assertTrue(workspace.exist("/assets/28f3c04ed7c76df43054fbafcb169af5ae20458a"));

		assertEquals("hello3", GET("http://localhost:9090/hello-1.0/hello"));
		assertEquals("hello3", GET("http://localhost:9090/hello-1.0u3/hello"));
	}

	private void sleep(int forSeconds) {
		try {
			Thread.sleep(forSeconds * 1000);
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		}
	}

	private String GET(String uri) {
		URL url;
		URLConnection connection = null;
		try {
			url = new URL(uri);
			connection = url.openConnection();
			return slurp(connection.getInputStream());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private String cleanProject(String appid, String version) {
		Project project = new Projects().createAndAddProject(appid, appid, version);
		workspace.save(project);
		return project.getArtifact().checksum();
	}

	protected static String userDir(String path) {
		return format("{0}/{1}", System.getProperty("user.dir"), path);
	}

	protected static String userDir(String path, String name) {
		return format("{0}/{1}/{2}", System.getProperty("user.dir"), path, name);
	}

}